home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 1 code / dynamo / rt.macros < prev    next >
Encoding:
Text File  |  1989-12-10  |  34.5 KB  |  1,472 lines  |  [TEXT/MPS ]

  1. *******************************************************
  2. *                        *
  3. * DYNAMO                        *
  4. *                        *
  5. * Apple II 8-bit runtime macros.            *
  6. * Copyright (C) 1989 Apple Computer.        *
  7. *                        *
  8. * Written by Eric Soldan, Apple II DTS        *
  9. *                        *
  10. *******************************************************
  11.  
  12. * These macros are interfaces for the runtime routines associated with them.
  13. * The runtime routines handle up to 128 integer variables, and up to 256
  14. * strings.  The integer functions are simple add,sub,mul,div, and others.
  15. * These others include mass-initialization, min, max, print decimal, etc.
  16. * The string functions are most of what is available in AppleSoft, in
  17. * various forms.  There is also support for multi-dimension arrays.
  18.  
  19. * The principle of the runtime routines is that the xreg holds a destination
  20. * variable number (for ints: 0-254, for strings: 0-255).  All runtimes preserve
  21. * the xreg, therefore, you can do multiple operations to a single variable
  22. * without having to reload the xreg.  The values that are used on the xreg
  23. * variable (the source data), is one of 3 forms for integers:
  24. *    1. 1-byte value
  25. *    2. 2-byte value
  26. *    3. 2-byte integer variable.
  27. * 1-byte values are placed in the acc.  2-byte values are placed in the acc,y
  28. * (acc=lo, y=hi).  2-byte integer variables have the variable number placed in
  29. * the yreg.  (The yreg is not preserved by the runtime routines.)
  30. * Once the source data is loaded (in acc, acc-y, or y), the proper call to the
  31. * runtime routines is made.  The 'proper' routine is based on the type of data
  32. * the source is.  (If the source is a variable, and we are adding, the macro
  33. * will call the addvar routine.)
  34.  
  35. * Strings are also referenced by number.  There are 3 tables for strings:
  36. *    1. String length table.
  37. *    2. Max string length table.
  38. *    3. Pointer table.
  39. * So, each string takes up four bytes, plus however long the max string length
  40. * is.  Having the pointer allows the program to point into memory that was
  41. * never loaded or initialized.  This can save time loading the application from
  42. * disk.  The string routines will never overwrite the buffer space alloced for
  43. * them.  The string will be truncated.  So, you can append strings without
  44. * worry about clobbering memory.
  45.  
  46.  
  47. *****************************************************************
  48. *****************************************************************
  49. *****************************************************************
  50.  
  51.  
  52. * These macros are called by other macros in this file.
  53.  
  54.     MACRO
  55.     acorm    &op
  56.     if    &substr(&op,1,1)='#' goto .imm
  57.     if    &substr(&op,1,1)<>'*' then
  58.     aerror    'non-variable parameter must be preceeded by a # or *'
  59.     mexit
  60.     endif
  61.     lda    &substr(&op,2,999)
  62.     mexit
  63. .imm    lda    #<&substr(&op,2,999)
  64.     mend
  65.  
  66.     MACRO
  67.     xcorm    &op
  68.     if    &substr(&op,1,1)='#' goto .imm
  69.     if    &substr(&op,1,1)<>'*' then
  70.     aerror    'non-variable parameter must be preceeded by a # or *'
  71.     mexit
  72.     endif
  73.     ldx    &substr(&op,2,999)
  74.     mexit
  75. .imm    ldx    #<&substr(&op,2,999)
  76.     mend
  77.  
  78.     MACRO
  79.     axcorm    &op
  80.     if    &substr(&op,1,1)='#' goto .imm
  81.     if    &substr(&op,1,1)<>'*' then
  82.     aerror    'non-variable parameter must be preceeded by a # or *'
  83.     mexit
  84.     endif
  85.     lda    &substr(&op,2,999)
  86.     ldx    &substr(&op,2,999)+1
  87.     mexit
  88. .imm    lda    #<&substr(&op,2,999)
  89.     ldx    #>&substr(&op,2,999)
  90.     mend
  91.  
  92.     MACRO
  93.     ycorm    &op
  94.     if    &substr(&op,1,1)='#' goto .imm
  95.     if    &substr(&op,1,1)<>'*' then
  96.     aerror    'non-variable parameter must be preceeded by a # or *'
  97.     mexit
  98.     endif
  99.     ldy    &substr(&op,2,999)
  100.     mexit
  101. .imm    ldy    #<&substr(&op,2,999)
  102.     mend
  103.  
  104.     MACRO
  105.     aycorm    &op
  106.     if    &substr(&op,1,1)='#' goto .imm
  107.     if    &substr(&op,1,1)<>'*' then
  108.     aerror    'non-variable parameter must be preceeded by a # or *'
  109.     mexit
  110.     endif
  111.     lda    &substr(&op,2,999)
  112.     ldy    &substr(&op,2,999)+1
  113.     mexit
  114. .imm    lda    #<&substr(&op,2,999)
  115.     ldy    #>&substr(&op,2,999)
  116.     mend
  117.  
  118.  
  119. *****************************************************************
  120. *****************************************************************
  121. *****************************************************************
  122.  
  123.  
  124. * This macro initializes everything necessary in the runtime and runtime
  125. * macros.  It initializes global macro variables and resets everything
  126. * in the runtime so the application can resume if the user presses a reset.
  127.     MACRO
  128. &lab    _rtreset
  129. &lab    jsr    rtreset
  130.     MEND
  131.  
  132.  
  133. ***************************************
  134.  
  135.  
  136. * This macro is used to turn on the hi-bit for characters that are sent to rtcout.
  137.     MACRO
  138. &lab    _hibitchrs
  139. &lab    jsr    hibitchrs
  140.     MEND
  141.  
  142.  
  143. ***************************************
  144.  
  145.  
  146. * This macro is used to turn off the hi-bit for characters that are sent to rtcout.
  147.     MACRO
  148. &lab    _lowbitchrs
  149. &lab    jsr    lowbitchrs
  150.     MEND
  151.  
  152.  
  153. ***************************************
  154.  
  155.  
  156. * This macro is used to make sure that characters sent to rtcout are used as-is.  There
  157. * will be no modification of the hi-bit.
  158.     MACRO
  159. &lab    _regchrs
  160. &lab    jsr    regchrs
  161.     MEND
  162.  
  163.  
  164. ***************************************
  165.  
  166.  
  167. * This macro prints a character.  This character is either already in the acc
  168. * (no operand), or what is described by the operand.  The operand can either
  169. * be an absolute or a value in memory.
  170. * (acorm means load Acc with a Constant OR Memory value).
  171.     MACRO
  172. &lab    _rtcout    &op
  173. &lab
  174.     if    &op='' goto .jsr
  175.     acorm    &op
  176. .jsr    jsr    rtcout
  177.     MEND
  178.  
  179.  
  180. ***************************************
  181.  
  182.  
  183. * This macro prints ascii data following the _write macro.  The write routine
  184. * works by using the return address as a pointer to the ascii data.  The ascii
  185. * data is terminated with a 0 (C-string style).  When the write routine
  186. * encounters a 0, it sets the return address so the when an rts is executed,
  187. * it returns to the code following the 0 terminator.  As many parameters as
  188. * are desired can be passed to this routine.  If the ascii data is more than
  189. * 1 line, end it with a comma,backslash to indicate line continuation.
  190.     MACRO
  191. &lab    _write
  192. &lab    
  193.     if    &syslist[1]='' then
  194.     aerror    '_write:  must have at least one parameter'
  195.     mexit
  196.     endif
  197.     jsr    write
  198.     lcla    &i,&n
  199. &i    seta    1
  200. &n    seta    &nbr(&syslist)
  201. .a    dc.b    &syslist[&i]
  202. &i    seta    &i+1
  203.     if    &i<=&n goto .a
  204.     dc.b    0
  205.     MEND
  206.  
  207.  
  208. ***************************************
  209.  
  210.  
  211. * This macro prints a carriage return.
  212.     MACRO
  213. &lab    _writecr
  214. &lab    jsr    writecr
  215.     MEND
  216.  
  217.  
  218. ***************************************
  219.  
  220.  
  221. * This macro prints a c string pointed to by the operand.
  222.     MACRO
  223. &lab    _wrcstr    &op
  224. &lab    aycorm    &op
  225.     jsr    wrcstr
  226.     MEND
  227.  
  228.  
  229. ***************************************
  230. ***************************************
  231. ***************************************
  232.  
  233.  
  234. * This macro sets signed mode.  Printing decimal numbers is affected by this.
  235.     MACRO
  236. &lab    _signed
  237. &lab    jsr    signed
  238.     MEND
  239.  
  240.  
  241. ***************************************
  242.  
  243.  
  244. * This macro sets unsigned mode.  Printing decimal numbers is affected by this.
  245.     MACRO
  246. &lab    _unsigned
  247. &lab    jsr    unsigned
  248.     MEND
  249.  
  250.  
  251. ***************************************
  252.  
  253.  
  254. * This macro does a two's compliment on the variable.
  255.     MACRO
  256. &lab    _chngsgn
  257. &lab    jsr    chngsgn
  258.     MEND
  259.  
  260.  
  261. ***************************************
  262.  
  263.  
  264. * This macro prints a 1-byte decimal value.  This value is either already in
  265. * the acc (no operand), or what is described by the operand.  The operand can
  266. * either be an absolute or a value in memory.
  267.     MACRO
  268. &lab    _decoutl    &op
  269. &lab    
  270.     if    &op='' goto .jsr
  271.     acorm    &op
  272. .jsr    jsr    decoutl
  273.     MEND
  274.  
  275.  
  276. ***************************************
  277.  
  278.  
  279. * This macro prints a 2-byte decimal value.  This value is stored in a
  280. * variable.  The variable number is either already in the xreg (no operand),
  281. * or is determined by the operand.
  282.     MACRO
  283. &lab    _vdecout    &op
  284. &lab    
  285.     if    &op='' goto .jsr
  286.     ldx    #<&op
  287. .jsr    jsr    vdecout
  288.     MEND
  289.  
  290.  
  291. ***************************************
  292.  
  293.  
  294. * This macro prints a 2-byte decimal value.  This value is either already in
  295. * the acc,y (no operand), or what is described by the operand.  The operand
  296. * can either be an absolute or a value in memory.
  297.     MACRO
  298. &lab    _decout    &op
  299. &lab    
  300.     if    &op='' goto .jsr
  301.     aycorm    &op
  302. .jsr    jsr    decout
  303.     MEND
  304.  
  305.  
  306. ***************************************
  307.  
  308.  
  309. * This macro sets pad mode for hex.  The value is either already in the acc
  310. * (no operand), or what is described by the operand.  The operand can either
  311. * be an absolute or a value in memory.  Printing hex numbers is affected by
  312. * this.
  313.     MACRO
  314. &lab    _hexpad    &op
  315. &lab    
  316.     if    &op='' goto .jsr
  317.     acorm    &op
  318. .jsr    jsr    hexpad
  319.     MEND
  320.  
  321.  
  322. ***************************************
  323.  
  324.  
  325. * This macro sets no pad mode for hex.  Printing hex numbers is affected by
  326. * this.
  327.     MACRO
  328. &lab    _hexnopad
  329. &lab    jsr    hexnopad
  330.     MEND
  331.  
  332.  
  333. ***************************************
  334.  
  335.  
  336. * This macro prints a 1-byte hex value.  This value is either already in the
  337. * acc (no operand), or what is described by the operand.  The operand can
  338. * either be an absolute or a value in memory.
  339.     MACRO
  340. &lab    _hexoutl    &op
  341. &lab    
  342.     if    &op='' goto .jsr
  343.     acorm    &op
  344. .jsr    jsr    hexoutl
  345.     MEND
  346.  
  347.  
  348. ***************************************
  349.  
  350.  
  351. * This macro prints a 2-byte hex value.  This value is stored in a variable.
  352. * The variable number is either already in the xreg (no operand), or is
  353. * determined by the operand.
  354.     MACRO
  355. &lab    _vhexout    &op
  356. &lab    
  357.     if    &op='' goto .jsr
  358.     ldx    #<&op
  359. .jsr    jsr    vhexout
  360.     MEND
  361.  
  362.  
  363. ***************************************
  364.  
  365.  
  366. * This macro prints a 2-byte hex value.  This value is either already in the
  367. * acc,y (no operand), or what is described by the operand.  The operand can
  368. * either be an absolute or a value in memory.
  369.     MACRO
  370. &lab    _hexout    &op
  371. &lab    
  372.     if    &op='' goto .jsr
  373.     aycorm    &op
  374. .jsr    jsr    hexout
  375.     MEND
  376.  
  377.  
  378. ***************************************
  379.  
  380.  
  381. * This macro adds a variable to the destination variable.  If there is no
  382. * op1, then the destination variable number is assumed to be in the xreg.
  383. * If there is no op2, then the source variable number is assumed to be in
  384. * the yreg.
  385.     MACRO
  386. &lab    _addvar    &op1,&op2
  387. &lab
  388.     if    &op1='' goto .a
  389.     ldx    #<&op1
  390. .a    if    &op2='' goto .jsr
  391.     ldy    #<&op2
  392. .jsr    jsr    addvar
  393.     mend
  394.  
  395.  
  396. ***************************************
  397.  
  398.  
  399. * This macro adds a 1-byte value to the destination variable.  If there is
  400. * no op1, then the destination variable number is assumed to be in the xreg.
  401. * If there is no op2, then the value is assumed to be in the acc.
  402.     MACRO
  403. &lab    _addl    &op1,&op2
  404. &lab
  405.     if    &op1='' goto .a
  406.     ldx    #<&op1
  407. .a    if    &op2='' goto .jsr
  408.     acorm    &op2
  409. .jsr    jsr    addconl
  410.     mend
  411.  
  412.  
  413. ***************************************
  414.  
  415.  
  416. * This macro adds a 2-byte value to the destination variable.  If there is
  417. * no op1, then the destination variable number is assumed to be in the xreg.
  418. * If there is no op2, then the value is assumed to be in acc,y.  aycorm works
  419. * like acorm, except for both the acc and yreg.
  420.     MACRO
  421. &lab    _add    &op1,&op2
  422. &lab
  423.     if    &op1='' goto .a
  424.     ldx    #<&op1
  425. .a    if    &op2='' goto .jsr
  426.     aycorm    &op2
  427. .jsr    jsr    addcon
  428.     mend
  429.  
  430.  
  431. ***************************************
  432.  
  433.  
  434. * This macro subtracts a variable from the destination variable.  If there is
  435. * no op1, then the destination variable number is assumed to be in the xreg.
  436. * If there is no op2, then the source variable number is assumed to be in
  437. * the yreg.
  438.     MACRO
  439. &lab    _subvar    &op1,&op2
  440. &lab
  441.     if    &op1='' goto .a
  442.     ldx    #<&op1
  443. .a    if    &op2='' goto .jsr
  444.     ldy    #<&op2
  445. .jsr    jsr    subvar
  446.     mend
  447.  
  448.  
  449. ***************************************
  450.  
  451.  
  452. * This macro subtracts a 1-byte value from the destination variable.  If there
  453. * is no op1, then the destination variable number is assumed to be in the xreg.
  454. * If there is no op2, then the value is assumed to be in the acc.
  455.     MACRO
  456. &lab    _subl    &op1,&op2
  457. &lab
  458.     if    &op1='' goto .a
  459.     ldx    #<&op1
  460. .a    if    &op2='' goto .jsr
  461.     acorm    &op2
  462. .jsr    jsr    subconl
  463.     mend
  464.  
  465.  
  466. ***************************************
  467.  
  468.  
  469. * This macro subtracts a 2-byte value from the destination variable.  If there
  470. * is no op1, then the destination variable number is assumed to be in the xreg.
  471. * If there is no op2, then the value is assumed to be in acc,y.  aycorm works
  472. * like acorm, except for both the acc and yreg.
  473.     MACRO
  474. &lab    _sub    &op1,&op2
  475. &lab
  476.     if    &op1='' goto .a
  477.     ldx    #<&op1
  478. .a    if    &op2='' goto .jsr
  479.     aycorm    &op2
  480. .jsr    jsr    subcon
  481.     mend
  482.  
  483.  
  484. ***************************************
  485.  
  486.  
  487. * This macro multiplies the destination variable by a variable.  If there is
  488. * no op1, then the destination variable number is assumed to be in the xreg.
  489. * If there is no op2, then the source variable number is assumed to be in
  490. * the yreg.
  491.     MACRO
  492. &lab    _mulvar    &op1,&op2
  493. &lab
  494.     if    &op1='' goto .a
  495.     ldx    #<&op1
  496. .a    if    &op2='' goto .jsr
  497.     ldy    #<&op2
  498. .jsr    jsr    mulvar
  499.     mend
  500.  
  501.  
  502. ***************************************
  503.  
  504.  
  505. * This macro multiplies the destination variable by a 1-byte value.  If there
  506. * is no op1, then the destination variable number is assumed to be in the xreg.
  507. * If there is no op2, then the value is assumed to be in the acc.
  508.     MACRO
  509. &lab    _mull    &op1,&op2
  510. &lab
  511.     if    &op1='' goto .a
  512.     ldx    #<&op1
  513. .a    if    &op2='' goto .jsr
  514.     acorm    &op2
  515. .jsr    jsr    mulconl
  516.     mend
  517.  
  518.  
  519. ***************************************
  520.  
  521.  
  522. * This macro multiplies the destination variable by a 2-byte value.  If there
  523. * is no op1, then the destination variable number is assumed to be in the xreg.
  524. * If there is no op2, then the value is assumed to be in acc,y.  aycorm works
  525. * like acorm, except for both the acc and yreg.
  526.     MACRO
  527. &lab    _mul    &op1,&op2
  528. &lab
  529.     if    &op1='' goto .a
  530.     ldx    #<&op1
  531. .a    if    &op2='' goto .jsr
  532.     aycorm    &op2
  533. .jsr    jsr    mulcon
  534.     mend
  535.  
  536.  
  537. ***************************************
  538.  
  539.  
  540. * This macro divides the destination variable by a variable.  If there is
  541. * no op1, then the destination variable number is assumed to be in the xreg.
  542. * If there is no op2, then the source variable number is assumed to be in
  543. * the yreg.  The remainder from the divide is in the acc,y.
  544.     MACRO
  545. &lab    _divvar    &op1,&op2
  546. &lab
  547.     if    &op1='' goto .a
  548.     ldx    #<&op1
  549. .a    if    &op2='' goto .jsr
  550.     ldy    #<&op2
  551. .jsr    jsr    divvar
  552.     mend
  553.  
  554.  
  555. ***************************************
  556.  
  557.  
  558. * This macro divides the destination variable by a 1-byte value.  If there
  559. * is no op1, then the destination variable number is assumed to be in the xreg.
  560. * If there is no op2, then the value is assumed to be in the acc.  The
  561. * remainder from the divide is in the acc,y.
  562.     MACRO
  563. &lab    _divl    &op1,&op2
  564. &lab
  565.     if    &op1='' goto .a
  566.     ldx    #<&op1
  567. .a    if    &op2='' goto .jsr
  568.     acorm    &op2
  569. .jsr    jsr    divconl
  570.     mend
  571.  
  572.  
  573. ***************************************
  574.  
  575.  
  576. * This macro divides the destination variable by a 2-byte value.  If there
  577. * is no op1, then the destination variable number is assumed to be in the xreg.
  578. * If there is no op2, then the value is assumed to be in acc,y.  aycorm works
  579. * like acorm, except for both the acc and yreg.  The remainder from the divide
  580. * is in the acc,y.
  581.     MACRO
  582. &lab    _div    &op1,&op2
  583. &lab
  584.     if    &op1='' goto .a
  585.     ldx    #<&op1
  586. .a    if    &op2='' goto .jsr
  587.     aycorm    &op2
  588. .jsr    jsr    divcon
  589.     mend
  590.  
  591.  
  592. ***************************************
  593.  
  594.  
  595. * This macro sets the current variable.  The current variable is defined by
  596. * a number in the xreg.  All runtime functions preserve the xreg, so multiple
  597. * operations can be done to the same variable without having to reload the xreg
  598. * with the variable number.
  599.     MACRO
  600. &lab    _var    &op
  601. &lab    ldx    #<&op
  602.     MEND
  603.  
  604.  
  605. ***************************************
  606.  
  607.  
  608. * This macro sets a variable to 0.  If there is no op1, then the destination
  609. * variable number is assumed to be in the xreg.
  610.     MACRO
  611. &lab    _set0    &op
  612. &lab    
  613.     if    &op='' goto .jsr
  614.     ldx    #<&op
  615. .jsr    jsr    setzero
  616.     MEND
  617.  
  618.  
  619. ***************************************
  620.  
  621.  
  622. * This macro sets a variable to another variable.  If there is no op1, then the
  623. * destination variable number is assumed to be in the xreg.  If there is no
  624. * op2, then the source variable number is assumed to be in the yreg.
  625.     MACRO
  626. &lab    _varcpy    &op1,&op2
  627. &lab    
  628.     if    &op1='' goto .a
  629.     ldx    #<&op1
  630. .a    if    &op2='' goto .jsr
  631.     ldy    #<&op2
  632. .jsr    jsr    seteq
  633.     mend
  634.  
  635.  
  636. ***************************************
  637.  
  638.  
  639. * This macro sets a variable to a 1-byte value.  If there is no op1, then the
  640. * destination variable number is assumed to be in the xreg.  If there is no
  641. * op2, then the value is assumed to be in the acc.
  642.     MACRO
  643. &lab    _setl    &op1,&op2
  644. &lab    
  645.     if    &op1='' goto .a
  646.     ldx    #<&op1
  647. .a    if    &op2='' goto .jsr
  648.     acorm    &op2
  649. .jsr    jsr    setconl
  650.     mend
  651.  
  652.  
  653. ***************************************
  654.  
  655.  
  656. * This macro sets a variable to a 2-byte value.  If there is no op1, then the
  657. * destination variable number is assumed to be in the xreg.  If there is no
  658. * op2, then the value is assumed to be in acc,y.
  659.     MACRO
  660. &lab    _set    &op1,&op2
  661. &lab    
  662.     if    &op1='' goto .a
  663.     ldx    #<&op1
  664. .a    if    &op2='' goto .jsr
  665.     aycorm    &op2
  666. .jsr    jsr    setcon
  667.     mend
  668.  
  669.  
  670. ***************************************
  671.  
  672.  
  673. * This macro is used to set a bunch of variables to constant values.
  674. * There must be a non-zero even number of parameters.  The odd parameters
  675. * are the variables, and the even parameters are the constant values for
  676. * the preceeding parameter.  The setvars routine uses the return address
  677. * as a pointer to the data (just like the write routine).  It simply
  678. * sets the designated variable to the designated constant until it
  679. * encounters a 255 as a variable value.  A 255 is reserved for this
  680. * purpose.  This macro places a 255 at the end of the data list
  681. * automatically.
  682.     MACRO
  683. &lab    _setvars
  684. &lab    
  685.     if    &syslist[2]='' then
  686.     aerror    '_setvars:  must have at least two parameters'
  687.     mexit
  688.     endif
  689.     jsr    setvars
  690.     lcla    &i,&j,&n
  691. &i    seta    1
  692. &j    seta    2
  693. &n    seta    &nbr(&syslist)
  694. .a    if    &syslist[&j]='' then
  695.     aerror    '_setvars:  must have even number of parameters'
  696.     mexit
  697.     endif
  698.     dc.b    &syslist[&i]
  699.     if    &substr(&syslist[&j],1,1)<>'#' then
  700.     aerror    '_setvars:  variables can only be set to constants -- missing #'
  701.     mexit
  702.     endif
  703.     dc.w    &substr(&syslist[&j],2,999)
  704. &i    seta    &i+2
  705. &j    seta    &j+2
  706.     if    &i<=&n goto .a
  707.     dc.b    255
  708.     MEND
  709.  
  710.  
  711. ***************************************
  712.  
  713.  
  714. * This macro swaps the two variables if the xreg variable is bigger than the
  715. * yreg variable.  If there is no op1, then the destination variable number is
  716. * assumed to be in the xreg.  If there is no op2, then the source variable
  717. * number is assumed to be in the yreg.
  718.     MACRO
  719. &lab    _minswap    &op1,&op2    
  720. &lab    
  721.     if    &op1='' goto .a
  722.     ldx    #<&op1
  723. .a    if    &op2='' goto .jsr
  724.     ldy    #<&op2
  725. .jsr    jsr    xlty
  726.     mend
  727.  
  728.  
  729. ***************************************
  730.  
  731.  
  732. * This macro swaps the two variables if the xreg variable is smaller than the
  733. * yreg variable.  If there is no op1, then the destination variable number is
  734. * assumed to be in the xreg.  If there is no op2, then the source variable
  735. * number is assumed to be in the yreg.
  736.     MACRO
  737. &lab    _maxswap    &op1,&op2    
  738. &lab    
  739.     if    &op1='' goto .a
  740.     ldx    #<&op1
  741. .a    if    &op2='' goto .jsr
  742.     ldy    #<&op2
  743. .jsr    jsr    xgty
  744.     mend
  745.  
  746.  
  747. ***************************************
  748.  
  749.  
  750. * This macro does a signed compare of two variables.  The equal status is true
  751. * if the variables are equal.  If the xreg variable is greater or equal, then
  752. * the carry is set.  If the xreg variable is smaller, then the carry is clear.
  753. * If there is no op1, then the variable number is assumed to be in the xreg.
  754. * If there is no op2, then the variable number is assumed to be in the yreg.
  755.     MACRO
  756. &lab    _vsgncmp    &op1,&op2    
  757. &lab
  758.     if    &op1='' goto .a
  759.     ldx    #<&op1
  760. .a    if    &op2='' goto .jsr
  761.     ldy    #<&op2
  762. .jsr    jsr    vifsgneq
  763.     mend
  764.  
  765.  
  766. ***************************************
  767.  
  768.  
  769. * This macro does an unsigned compare of two variables.  The equal status is
  770. * true if the variables are equal.  If the xreg variable is greater or equal,
  771. * then the carry is set.  If the xreg variable is smaller, then the carry is
  772. * clear.  If there is no op1, then the variable number is assumed to be in the
  773. * xreg.  If there is no op2, then the variable number is assumed to be in the
  774. * yreg.
  775.     MACRO
  776. &lab    _vcmp    &op1,&op2    
  777. &lab
  778.     if    &op1='' goto .a
  779.     ldx    #<&op1
  780. .a    if    &op2='' goto .jsr
  781.     ldy    #<&op2
  782. .jsr    jsr    vifequal
  783.     mend
  784.  
  785.  
  786. ***************************************
  787.  
  788.  
  789. * This macro works the same as _vsgncmp, except that it compares a variable
  790. * against a constant or value from memory at a specified location.
  791.     MACRO
  792. &lab    _sgncmp    &op1,&op2    
  793. &lab
  794.     if    &op1='' goto .a
  795.     ldx    #<&op1
  796. .a    if    &op2='' goto .jsr
  797.     aycorm    &op2
  798. .jsr    jsr    ifsgneq
  799.     mend
  800.  
  801.  
  802. ***************************************
  803.  
  804.  
  805. * This macro works the same as _vcmp, except that it compares a variable
  806. * against a constant or value from memory at a specified location.
  807.     MACRO
  808. &lab    _cmp    &op1,&op2    
  809. &lab
  810.     if    &op1='' goto .a
  811.     ldx    #<&op1
  812. .a    if    &op2='' goto .jsr
  813.     aycorm    &op2
  814. .jsr    jsr    ifequal
  815.     mend
  816.  
  817.  
  818. ***************************************
  819. ***************************************
  820. ***************************************
  821.  
  822.  
  823. * This macro is used to seed the random number generator.  If there is
  824. * no op1, then the random seed is assumed to be in the acc,y.
  825.     MACRO
  826. &lab    _rndseed    &op
  827. &lab    
  828.     if    &op='' goto .jsr
  829.     aycorm    &op
  830. .jsr    jsr    seedrandom
  831.     MEND
  832.  
  833.  
  834. ***************************************
  835.  
  836.  
  837. * This macro is used to return a random number from 0 to op - 1.  If there is
  838. * no op1, then the random number limit is assumed to be in the acc,y.
  839.     MACRO
  840. &lab    _random    &op
  841. &lab    
  842.     if    &op='' goto .jsr
  843.     aycorm    &op
  844. .jsr    jsr    calcrandom
  845.     MEND
  846.  
  847.  
  848. ***************************************
  849. ***************************************
  850. ***************************************
  851.  
  852.  
  853. * This macro takes the value of a string and returns it in the acc,y.
  854. * If there is no op1, then the string number is assumed to be in the xreg.
  855.     MACRO
  856. &lab    _strval    &op
  857. &lab
  858.     if    &op='' goto .jsr
  859.     ldx    #<&op
  860. .jsr    jsr    strval
  861.     mend
  862.  
  863.  
  864. ***************************************
  865.  
  866.  
  867. * This macro takes the value of op1 string starting at op2 character and
  868. * returns it in the acc,y.  If there is no op1, then the string number is
  869. * assumed to be in the xreg.  If there is no op2, then the character number
  870. * is assumed to be in the yreg.
  871.     MACRO
  872. &lab    _midstrval &op1,&op2
  873. &lab
  874.     if    &op1='' goto .a
  875.     ldx    #<&op1
  876. .a    if    &op2='' goto .jsr
  877.     ycorm    &op2
  878. .jsr    jsr    midstrval
  879.     mend
  880.  
  881.  
  882. ***************************************
  883.  
  884.  
  885. * This macro prints the entire string.  If there is no op1, then the string
  886. * number is assumed to be in the xreg.
  887.     MACRO
  888. &lab    _prstr    &op
  889. &lab    
  890.     if    &op='' goto .jsr
  891.     ldx    #<&op
  892. .jsr    jsr    prstr
  893.     MEND
  894.  
  895.  
  896. ***************************************
  897.  
  898.  
  899. * This macro prints op1 string starting at the first character for op2
  900. * characters.  If there is no op1, then the string number is assumed to be
  901. * in the xreg.  If there is no op2, then the number of characters is assumed
  902. * to be in the acc.
  903.     MACRO
  904. &lab    _prleftstr &op1,&op2
  905. &lab
  906.     if    &op1='' goto .a
  907.     ldx    #<&op1
  908. .a    if    &op2='' goto .jsr
  909.     acorm    &op2
  910. .jsr    jsr    prleftstr
  911.     mend
  912.  
  913.  
  914. ***************************************
  915.  
  916.  
  917. * This macro prints op1 string starting at the op2 character for op3
  918. * characters.  If there is no op1, then the string number is assumed to be
  919. * in the xreg.  If there is no op2, then the character number is assumed to
  920. * be in the yreg.  If there is no op3, then the number of characters is
  921. * assumed to be in the acc.
  922.     MACRO
  923. &lab    _prmidstr &op1,&op2,&op3
  924. &lab
  925.     if    &op1='' goto .a
  926.     ldx    #<&op1
  927. .a    if    &op2='' goto .b
  928.     ycorm    &op2
  929. .b    if    &op3='' goto .jsr
  930.     acorm    &op3
  931. .jsr    jsr    prmidstr
  932.     mend
  933.  
  934.  
  935. ***************************************
  936.  
  937.  
  938. * This macro copies op3 characters from op2 string to op1 string.  If there
  939. * is no op1, then the destination string number is assumed to be in the xreg.
  940. * If there is no op2, then the source string number is assumed to be in the
  941. * yreg.  If there is no op3, then the number of characters is assumed to be
  942. * in the acc.
  943.     MACRO
  944. &lab    _leftstrcpy &op1,&op2,&op3
  945. &lab    
  946.     if    &op1='' goto .a
  947.     ldx    #<&op1
  948. .a    if    &op2='' goto .b
  949.     ldy    #<&op2
  950. .b    if    &op3='' goto .jsr
  951.     acorm    &op3
  952. .jsr    jsr    leftstrcpy
  953.     mend
  954.  
  955.  
  956. ***************************************
  957.  
  958.  
  959. * This macro copies op2 string to op1 string.  If there is no op1, then the
  960. * destination string number is assumed to be in the xreg.  If there is no op2,
  961. * then the source string number is assumed to be in the yreg.
  962.     MACRO
  963. &lab    _strcpy &op1,&op2
  964. &lab    
  965.     if    &op1='' goto .a
  966.     ldx    #<&op1
  967. .a    if    &op2='' goto .jsr
  968.     ldy    #<&op2
  969. .jsr    jsr    strcpy
  970.     mend
  971.  
  972.  
  973. ***************************************
  974.  
  975.  
  976. * This macro copies op4 characters, starting at op3 character from op2 string
  977. * to op1 string.  If there is no op1, then the destination string number is
  978. * assumed to be in the xreg.  If there is no op2, then the source string number
  979. * is assumed to be in the yreg.  If there is no op3, then the character number
  980. * is assumed to be in the acc.  If there is no op4, then all characters to the
  981. * end of the source string will be copied to the destination string.  The op4
  982. * case is the only case where the assumed value is a particular value (#255),
  983. * instead of what is in a register.  This is the case because there are only
  984. * three registers.
  985.     MACRO
  986. &lab    _midstrcpy &op1,&op2,&op3,&op4
  987. &lab
  988.     if    &op4='' goto .b
  989.     if    &op3<>'' goto .a
  990.     pha
  991. .a
  992.     acorm    &op4
  993.     sta    numtocopy
  994.     if    &op3<>'' goto .b
  995.     pla
  996. .b    if    &op1='' goto .c
  997.     ldx    #<&op1
  998. .c    if    &op2='' goto .d
  999.     ldy    #<&op2
  1000. .d    if    &op3='' goto .jsr
  1001.     acorm    &op3
  1002. .jsr    jsr    midstrcpy
  1003.     mend
  1004.  
  1005.  
  1006. ***************************************
  1007.  
  1008.  
  1009. * This macro concatenates op3 characters of op2 string onto op1 string.  If
  1010. * there is no op1, then the destination string number is assumed to be in the
  1011. * xreg.  If there is no op2, then the source string number is assumed to be in
  1012. * the yreg.  If there is no op3, then the number of characters is assumed to
  1013. * be in the acc.
  1014.     MACRO
  1015. &lab    _leftstrcat &op1,&op2,&op3
  1016. &lab    
  1017.     if    &op1='' goto .a
  1018.     ldx    #<&op1
  1019. .a    if    &op2='' goto .b
  1020.     ldy    #<&op2
  1021. .b    if    &op3='' goto .jsr
  1022.     acorm    &op3
  1023. .jsr    jsr    leftstrcat
  1024.     mend
  1025.  
  1026.  
  1027. ***************************************
  1028.  
  1029.  
  1030. * This macro concatenates op2 string onto op1 string.  If there is no op1,
  1031. * then the destination string number is assumed to be in the xreg.  If there
  1032. * is no op2, then the source string number is assumed to be in the yreg.
  1033.     MACRO
  1034. &lab    _strcat &op1,&op2
  1035. &lab    
  1036.     if    &op1='' goto .a
  1037.     ldx    #<&op1
  1038. .a    if    &op2='' goto .jsr
  1039.     ldy    #<&op2
  1040. .jsr    jsr    strcat
  1041.     mend
  1042.  
  1043.  
  1044. ***************************************
  1045.  
  1046.  
  1047. * This macro concatenates op4 characters starting at op3 character from op2
  1048. * string onto op1 string.  If there is no op1, then the destination string
  1049. * number is assumed to be in the xreg.  If there is no op2, then the source
  1050. * string number is assumed to be in the yreg.  If there is no op3, then the
  1051. * character number is assumed to be in the acc.  If there is no op4, then all
  1052. * characters to the end of the source string will be concatenated to the
  1053. * destination string.  The op4 case is the only case where the assumed value
  1054. * is a particular value (#255), instead of what is in a register.  This is
  1055. * the case because there are only three registers.
  1056.     MACRO
  1057. &lab    _midstrcat &op1,&op2,&op3,&op4
  1058. &lab
  1059.     if    &op4='' goto .a
  1060.     pha
  1061.     acorm    &op4
  1062.     sta    numtocopy
  1063.     pla
  1064. .a    if    &op1='' goto .b
  1065.     ldx    #<&op1
  1066. .b    if    &op2='' goto .c
  1067.     ldy    #<&op2
  1068. .c    if    &op3='' goto .jsr
  1069.     acorm    &op3
  1070. .jsr    jsr    midstrcat
  1071.     mend
  1072.  
  1073.  
  1074. ***************************************
  1075.  
  1076.  
  1077. * This macro is used to take some literal string data and place it into
  1078. * a string.  It works very much like the write routine, except that it
  1079. * copies the characters into a string instead of printing them.  Operand
  1080. * 1 is the string variable, if there is one designated.  If there is not
  1081. * one designated, then the x-reg is assumed to already hold it.  There
  1082. * then must be a second parameter.  This parameter would be string data.
  1083. * There may be other parameters, which would also hold string data.
  1084. * When all data parameters are used by this macro, the macro then places
  1085. * a 0 terminator to indicate the end of the literal data.
  1086.     MACRO
  1087. &lab    _litstr
  1088. &lab    
  1089.     if    &syslist[2]='' then
  1090.     aerror    '_litstr:  must have a second parameter'
  1091.     mexit
  1092.     endif
  1093.     if    &syslist[1]='' goto .jsr
  1094.     ldx    #<&syslist[1]
  1095. .jsr    jsr    litstr
  1096.     lcla    &i,&n
  1097. &i    seta    2
  1098. &n    seta    &nbr(&syslist)
  1099. .a    dc.b    &syslist[&i]
  1100. &i    seta    &i+1
  1101.     if    &i<=&n goto .a
  1102.     dc.b    0
  1103.     MEND
  1104.  
  1105.  
  1106. ***************************************
  1107.  
  1108.  
  1109. * This macro returns the op2th character of op1 string.  If there is no op1,
  1110. * then the destination string number is assumed to be in the xreg.  If there
  1111. * is no op2, then the character number is assumed to be in the acc.
  1112.     MACRO
  1113. &lab    _strchr &op1,&op2
  1114. &lab    
  1115.     if    &op1='' goto .a
  1116.     ldx    #<&op1
  1117. .a    if    &op2='' goto .jsr
  1118.     acorm    &op2
  1119. .jsr    jsr    strchr
  1120.     mend
  1121.  
  1122.  
  1123. ***************************************
  1124.  
  1125.  
  1126. * This macro returns the physical location of op1 string in memory.  The
  1127. * string location is returned in acc,y.If there is no op1, then the
  1128. * destination string number is assumed to be in the xreg.
  1129.     MACRO
  1130. &lab    _strloc &op1
  1131. &lab    
  1132.     if    &op1='' goto .jsr
  1133.     ldx    #<&op1
  1134. .jsr    jsr    strloc
  1135.     mend
  1136.  
  1137.  
  1138. ***************************************
  1139.  
  1140.  
  1141.     MACRO
  1142. &lab    _cstr
  1143. &lab    
  1144.     if    &syslist[1]='' then
  1145.     aerror    '_write:  must have at least one parameter'
  1146.     mexit
  1147.     endif
  1148.     lcla    &i,&n
  1149. &i    seta    1
  1150. &n    seta    &nbr(&syslist)
  1151. .a    dc.b    &syslist[&i]
  1152. &i    seta    &i+1
  1153.     if    &i<=&n goto .a
  1154.     dc.b    0
  1155.     MEND
  1156.  
  1157.  
  1158. ***************************************
  1159. ***************************************
  1160. ***************************************
  1161.  
  1162.  
  1163. * This macro sets the read data pointer.  If there is no op, then the address
  1164. * for reading data is assumed to be in the acc,y.
  1165.     MACRO
  1166. &lab    _restore    &op
  1167. &lab
  1168.     if    &op='' goto .jsr
  1169.     aycorm    &op
  1170. .jsr    jsr    restore
  1171.     MEND
  1172.  
  1173.  
  1174. ***************************************
  1175.  
  1176.  
  1177. * This macro reads an int from the current data pointer and advances the
  1178. * pointer by two bytes.  If there is no op1, then the destination variable
  1179. * number is assumed to be in the xreg.
  1180.     MACRO
  1181. &lab    _readint    &op
  1182. &lab    
  1183.     if    &op='' goto .jsr
  1184.     ldx    #<&op
  1185. .jsr    jsr    readint
  1186.     MEND
  1187.  
  1188.  
  1189. ***************************************
  1190.  
  1191.  
  1192. * This macro reads string data into the designated string until the
  1193. * end-of-string character is encountered.  The data pointer is then set to
  1194. * point after this end-of-string character.  If there is no op1, then the
  1195. * destination string number is assumed to be in the xreg.
  1196.     MACRO
  1197. &lab    _readstr    &op
  1198. &lab    
  1199.     if    &op='' goto .jsr
  1200.     ldx    #<&op
  1201. .jsr    jsr    readstr
  1202.     MEND
  1203.  
  1204.  
  1205. ***************************************
  1206.  
  1207.  
  1208. * This macro is used to set the end-of-string character for _readstr.  If
  1209. * there is no op1, then the _readstr ending character is assumed to be in
  1210. * the acc.
  1211.     MACRO
  1212. &lab    _readend    &op
  1213. &lab    
  1214.     if    &op='' goto .jsr
  1215.     acorm    &op
  1216. .jsr    jsr    readend
  1217.     MEND
  1218.  
  1219.  
  1220. ***************************************
  1221. ***************************************
  1222. ***************************************
  1223.  
  1224.  
  1225. * This macro is used to define some memory as an array of up to
  1226. * 4 dimensions.  The first parameter is the location of the
  1227. * array, or where the location of the array is stored.  The second
  1228. * parameter is the size of the elements, (b)yte or (w)ord.  The 
  1229. * third parameter is the first dimension.  The macro and routines
  1230. * actually ignore this dimension, since it would only be used for
  1231. * range checking anyway.  The fourth through sixth parameters are
  1232. * optional.  The more parameters, the more dimensions in the array.
  1233.     MACRO
  1234. &lab    _array    &loc,&elesize,&op1,&op2,&op3,&op4
  1235. &lab    
  1236.     if    &loc='' goto .a
  1237.     aycorm    &loc
  1238. .a    jsr    arraybase
  1239.     if    &op4='' goto .b
  1240.     if    &substr(&op4,1,1)<>'#' then
  1241. .err    aerror    '_array:  dimensions must be constants --  parameter must be preceeded by a #'
  1242.     mexit
  1243.     endif
  1244. .b    if    &op3='' goto .c
  1245.     if    &substr(&op3,1,1)<>'#' goto .err
  1246. .c    if    &op2='' goto .d
  1247.     if    &substr(&op2,1,1)<>'#' goto .err
  1248. .d    if    &op1='' goto .e
  1249.     if    &substr(&op1,1,1)<>'#' goto .err
  1250. .e    if    &substr(&elesize,1,1)='b' goto .byte
  1251.     if    &substr(&elesize,1,1)='B' goto .byte
  1252.     if    &substr(&elesize,1,1)='w' goto .word
  1253.     if    &substr(&elesize,1,1)='W' goto .word
  1254.     aerror    '_array:  element size can only be byte or word (b,w)'
  1255. .word    if    &op4>'' goto .w4
  1256.     if    &op3>'' goto .w3
  1257.     if    &op2>'' goto .w2
  1258.     mexit
  1259. .w2    lda    #<&substr(&op2,2,999)*2
  1260.     ldy    #>&substr(&op2,2,999)*2
  1261.     jsr    dim1size
  1262.     mexit
  1263. .w3    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)*2
  1264.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)*2
  1265.     jsr    dim1size
  1266.     lda    #<&substr(&op3,2,999)*2
  1267.     ldy    #>&substr(&op3,2,999)*2
  1268.     jsr    dim2size
  1269.     mexit
  1270. .w4    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1271.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1272.     jsr    dim1size
  1273.     lda    #<&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1274.     ldy    #>&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1275.     jsr    dim2size
  1276.     lda    #<&substr(&op4,2,999)*2
  1277.     ldy    #>&substr(&op4,2,999)*2
  1278.     jsr    dim3size
  1279.     mexit
  1280. .byte    if    &op4>'' goto .b4
  1281.     if    &op3>'' goto .b3
  1282.     if    &op2>'' goto .b2
  1283. .b2    lda    #<&substr(&op2,2,999)
  1284.     ldy    #>&substr(&op2,2,999)
  1285.     jsr    dim1size
  1286.     mexit
  1287. .b3    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)
  1288.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)
  1289.     jsr    dim1size
  1290.     lda    #<&substr(&op3,2,999)
  1291.     ldy    #>&substr(&op3,2,999)
  1292.     jsr    dim2size
  1293.     mexit
  1294. .b4    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)
  1295.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)
  1296.     jsr    dim1size
  1297.     lda    #<&substr(&op3,2,999)*&substr(&op4,2,999)
  1298.     ldy    #>&substr(&op3,2,999)*&substr(&op4,2,999)
  1299.     jsr    dim2size
  1300.     lda    #<&substr(&op4,2,999)
  1301.     ldy    #>&substr(&op4,2,999)
  1302.     jsr    dim3size
  1303.     mend
  1304.  
  1305.  
  1306. ***************************************
  1307.  
  1308.  
  1309. * This macro is used to index into the current array (defined by _array).
  1310. * The whole goal of the array handling is to index down to the row level.
  1311. * Once at the row level, you use the right-most subscript to index into
  1312. * that row.  This makes working on a row very fast, since all subscripts
  1313. * are not involved each time.  So, _index would be used for all subscripts
  1314. * except for the last subscript.  The parameter can either be a constant,
  1315. * (preceeded with a #) or can be a location in ram that holds the index
  1316. * (preceeded with an *).
  1317.     MACRO
  1318. &lab    _index    &op1,&op2,&op3
  1319. &lab
  1320.     if    &op1='' goto .a
  1321.     aycorm    &op1
  1322.     jsr    arrayindx1
  1323. .a    if    &op2='' goto .b
  1324.     aycorm    &op2
  1325.     jsr    arrayindx2
  1326. .b    if    &op3='' goto .c
  1327.     aycorm    &op3
  1328.     jsr    arrayindx3
  1329. .c    mend
  1330.  
  1331.  
  1332. ***************************************
  1333.  
  1334.  
  1335. * This macro works the same as _index, except that the index is stored
  1336. * in the variable indicated.
  1337.     MACRO
  1338. &lab    _vindex    &op1,&op2,&op3
  1339. &lab
  1340.     if    &op1='' goto .a
  1341.     ldy    #<&op1
  1342.     jsr    varyindx1
  1343. .a    if    &op2='' goto .b
  1344.     ldy    #<&op2
  1345.     jsr    varyindx2
  1346. .b    if    &op3='' goto .c
  1347.     ldy    #<&op3
  1348.     jsr    varyindx3
  1349. .c    mend
  1350.  
  1351.  
  1352. ***************************************
  1353.  
  1354.  
  1355. * This macro gets a byte from the working row of the current array.
  1356. * The final index parameter is used to index into this row.
  1357.     MACRO
  1358. &lab    _getb    &op1,&op2
  1359. &lab
  1360.     if    &op1='' goto .a
  1361.     ldx    #<&op1
  1362. .a    if    &op2='' goto .jsr
  1363.     aycorm    &op2
  1364. .jsr    jsr    getelel
  1365.     mend
  1366.  
  1367.  
  1368. ***************************************
  1369.  
  1370.  
  1371. * This macro is works the same as _getb, except that the index is
  1372. * stored in a variable.
  1373.     MACRO
  1374. &lab    _vgetb    &op1,&op2
  1375. &lab
  1376.     if    &op1='' goto .a
  1377.     ldx    #<&op1
  1378. .a    if    &op2='' goto .jsr
  1379.     ldy    #<&op2
  1380. .jsr    jsr    vgetelel
  1381.     mend
  1382.  
  1383.  
  1384. ***************************************
  1385.  
  1386.  
  1387. * This macro is the same as _getb, except that it gets a word.
  1388.     MACRO
  1389. &lab    _getw    &op1,&op2
  1390. &lab
  1391.     if    &op1='' goto .a
  1392.     ldx    #<&op1
  1393. .a    if    &op2='' goto .jsr
  1394.     aycorm    &op2
  1395. .jsr    jsr    getele
  1396.     mend
  1397.  
  1398.  
  1399. ***************************************
  1400.  
  1401.  
  1402. * This macro is the same as _vgetb, except that it gets a word.
  1403.     MACRO
  1404. &lab    _vgetw    &op1,&op2
  1405. &lab
  1406.     if    &op1='' goto .a
  1407.     ldx    #<&op1
  1408. .a    if    &op2='' goto .jsr
  1409.     ldy    #<&op2
  1410. .jsr    jsr    vgetele
  1411.     mend
  1412.  
  1413.  
  1414. ***************************************
  1415.  
  1416.  
  1417. * This macro is the same as _getb, except that it stores a byte.
  1418.     MACRO
  1419. &lab    _putb    &op1,&op2
  1420. &lab
  1421.     if    &op1='' goto .a
  1422.     ldx    #<&op1
  1423. .a    if    &op2='' goto .jsr
  1424.     aycorm    &op2
  1425. .jsr    jsr    putelel
  1426.     mend
  1427.  
  1428.  
  1429. ***************************************
  1430.  
  1431.  
  1432. * This macro is the same as _vgetb, except that it stores a byte.
  1433.     MACRO
  1434. &lab    _vputb    &op1,&op2
  1435. &lab
  1436.     if    &op1='' goto .a
  1437.     ldx    #<&op1
  1438. .a    if    &op2='' goto .jsr
  1439.     ldy    #<&op2
  1440. .jsr    jsr    vputelel
  1441.     mend
  1442.  
  1443.  
  1444. ***************************************
  1445.  
  1446.  
  1447. * This macro is the same as _getw, except that it stores a word.
  1448.     MACRO
  1449. &lab    _putw    &op1,&op2
  1450. &lab
  1451.     if    &op1='' goto .a
  1452.     ldx    #<&op1
  1453. .a    if    &op2='' goto .jsr
  1454.     aycorm    &op2
  1455. .jsr    jsr    putele
  1456.     mend
  1457.  
  1458.  
  1459. ***************************************
  1460.  
  1461.  
  1462. * This macro is the same as _vgetw, except that it stores a word.
  1463.     MACRO
  1464. &lab    _vputw    &op1,&op2
  1465. &lab
  1466.     if    &op1='' goto .a
  1467.     ldx    #<&op1
  1468. .a    if    &op2='' goto .jsr
  1469.     ldy    #<&op2
  1470. .jsr    jsr    vputele
  1471.     mend
  1472.